package thesis.javaclass;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import thesis.database.Factory;
import thesis.database.TaxiJDBCTemplate;

public class TaxiFinderServer implements Runnable {
	private static final int PORT = 30000;
	private static ServerSocket serverSocket;

	public TaxiFinderServer() {

	}

	@Override
	public void run() {
		try {
			serverSocket = new ServerSocket(PORT);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		while (true) {
			try {
				Socket socket = serverSocket.accept();
				Scanner input = new Scanner(socket.getInputStream());
				String message = input.nextLine();
				String[] data = message.split(";");
				String phoneNumber = data[0];
				String address = data[1];
				double longitude = Double.parseDouble(data[2]);
				double latitude = Double.parseDouble(data[3]);
				int numberOfSeat = Integer.parseInt(data[4]);
				ServiceRequest serviceRequest = new ServiceRequest(
						new ArrayList<TempAccept>());
				serviceRequest.setPhoneNumber(phoneNumber);
				serviceRequest.setAddress(address);
				serviceRequest.setNumberOfSeat(numberOfSeat);
				serviceRequest.getCoordinate().add(longitude);
				serviceRequest.getCoordinate().add(latitude);
				ServiceList.add(phoneNumber, serviceRequest);

				TaxiFinner tf = new TaxiFinner(serviceRequest, socket);
				Thread thread = new Thread(tf);
				thread.start();

			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	class TaxiFinner implements Runnable {
		private ServiceRequest serviceRequest;
		TaxiJDBCTemplate taxi = (TaxiJDBCTemplate) Factory
				.createJDBCTemplate("taxiJDBCTemplate");
		private Socket socket;

		public TaxiFinner(ServiceRequest serviceRequest, Socket socket) {
			this.serviceRequest = serviceRequest;
			this.socket = socket;
		}

		public void run() {
			WebComunicator webCom = new WebComunicator();
			Thread webThread = new Thread(webCom);
			webThread.start();

			double distance = 1.5;
			do {
				serviceRequest.getAcceptTaxiImeis().clear();
				boolean flag = true; // this flag is mean that it does not exist
				// any free taxi
				// gui thong tin den Server
				ArrayList<Double> boudingCoordinate = MapFunction
						.getBoundingCoordinates(serviceRequest.getCoordinate()
								.get(0), serviceRequest.getCoordinate().get(1),
								distance);
				TaxiJDBCTemplate taxiTem = (TaxiJDBCTemplate) Factory
						.createJDBCTemplate("taxiJDBCTemplate");
				List<Integer> listId = taxiTem
						.getListTaxiIdByBoundingCoordinates(
								boudingCoordinate.get(0),
								boudingCoordinate.get(1),
								boudingCoordinate.get(2),
								boudingCoordinate.get(3),
								serviceRequest.getNumberOfSeat());

				// dinh dang chuoi gui di :
				// phoneNumber-address-latitudeOfCustomer-longitudeOfCustomer-taxiId-taxiId----taxiid;

				// /get port by id to send to taxi listener for demo///////
				// ///////////////////////////////////////////////////////
				if (listId.size() > 0) {

					for (int i = 0; i < listId.size(); i++) {
						// System.out.println(ServiceList.isBusy(taxi.getImeiById(listId.get(i))));
						if (!ServiceList
								.isBusy(taxi.getImeiById(listId.get(i)))) {
							flag = false;// note that there is exist at least
											// one
											// free taxi

							ServiceList
									.setBusy(taxi.getImeiById(listId.get(i)));
							BroadcastServer bs = new BroadcastServer(
									taxi.getPortById(listId.get(i)),
									taxi.getImeiById(listId.get(i)),
									taxi.getNumberPlateById(listId.get(i)),
									serviceRequest);
							Thread thread = new Thread(bs);
							thread.start();
						}

					}
					if (flag) {
						System.out.println(Thread.currentThread().getName()
								+ " : R = " + distance
								+ " : All taxies are busy");
					}
				} else {
					System.out.println("R = " + distance
							+ ": not found any taxi");
				}
				try {
					Thread.currentThread();
					Thread.sleep(20000); // 15s for confirm first time;
					if (serviceRequest.getAcceptTaxiImeis().size() != 0)
						serviceRequest.setFinished(true);
					int count = 0;
					while (true) {
						Thread.sleep(1);
						count++;
						if (count == 17000
								|| serviceRequest.getSelectedImei() != "") {
							break;
						}

					}

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				if (serviceRequest.getSelectedImei().equals(""))
					clearData();
				distance += 1.5;
			} while (serviceRequest.getSelectedImei().equals(""));

		}

		private void clearData() {
			serviceRequest.getAcceptTaxiImeis().clear();
			serviceRequest.setFinished(false);
		}

		class WebComunicator implements Runnable {

			@Override
			public void run() {
				try {
					PrintWriter output = new PrintWriter(
							socket.getOutputStream(), true);
					int count = serviceRequest.getAcceptTaxiImeis().size();
					while (true) {
						String message = "";
						if (!serviceRequest.getSelectedImei().equals("")) {
							message = serviceRequest.getSelectedImei() + ",1";
							output.println(message);
							socket.close();
							break;
						} else if (serviceRequest.getAcceptTaxiImeis().size() < count) {
							output.println("0,0");
							count = serviceRequest.getAcceptTaxiImeis().size();
						} else if (serviceRequest.getAcceptTaxiImeis().size() != count) {
							count = serviceRequest.getAcceptTaxiImeis().size();
							message = serviceRequest.getAcceptTaxiImeis().get(
									count - 1)
									+ ",0";
							output.println(message);

						}

						Thread.sleep(500);

					}
				} catch (IOException e) {
					System.out.println(getClass().getName() + ": No I/O");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}
		}

	}

}
